package com.tyx.chargingpile.handler;

import com.tyx.chargingpile.Enum.ServiceExceptionEume;
import com.tyx.chargingpile.cache.SocketChannelMap;
import com.tyx.chargingpile.config.NettyConfig;
import com.tyx.chargingpile.service.MessageFactoryService;
import com.tyx.chargingpile.service.MessageService;
import com.tyx.chargingpile.service.exception.ServiceExcep;
import com.tyx.chargingpile.util.Util;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ChargingHandler extends ChannelInboundHandlerAdapter {

    private MessageFactoryService messageFactoryService;

    public ChargingHandler(MessageFactoryService messageFactoryService){
        this.messageFactoryService = messageFactoryService;
    }



    private final static Logger LOGGER = LoggerFactory.getLogger(ChargingHandler.class);

    /**
     * 客户端与服务端创建连接的时候调用
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        LOGGER.info("客户端" + ctx.channel().id().toString() + "连接开始...");
        NettyConfig.group.add(ctx.channel());
        LOGGER.info("客户端" + ctx.channel().id().toString() + "连接完成");
    }

    /**
     * 客户端与服务端断开连接时调用
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        LOGGER.info("客户端" + ctx.channel().id().toString() + "与服务端连接关闭...");
        String pileNum = SocketChannelMap.getDeviceId(ctx.channel().id().toString());
        NettyConfig.group.remove(ctx.channel());
        SocketChannelMap.removeChannelMapByChannelId(ctx.channel().id().toString());
        LOGGER.info("客户端" + ctx.channel().id().toString() + "连接关闭" + ",桩编号" + pileNum);
        ctx.close(); // 连接关闭
    }

    /**
     * 服务端接收客户端发送过来的数据结束之后调用
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
//        String pileNum = SocketChannelMap.getDeviceId(ctx.channel().id().toString());
//        LOGGER.info("客户端"+ ctx.channel().id().toString() + ",桩编号:" + pileNum +",信息接收完毕...");
    }

    /**
     * 工程出现异常的时候调用
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        if(cause instanceof ServiceExcep){
            // TODO: 2019/4/17 目前设计好如何处理业务异常信息
        LOGGER.error("客户端"+ ctx.channel().id().toString() +":"+((ServiceExcep) cause).getMsg()+"data:"+((ServiceExcep) cause).getData());
        }
        else{
            ctx.close();
        }
    }

    /**
     * 服务端处理客户端websocket请求的核心方法，这里接收了客户端发来的信息
     */
    @Override
    public void channelRead(ChannelHandlerContext channelHandlerContext, Object info) throws Exception {
        String pileNum = SocketChannelMap.getDeviceId(channelHandlerContext.channel().id().toString());
        ByteBuf buf = (ByteBuf) info;
        byte[] req = new byte[buf.readableBytes()];
        buf.readBytes(req);
        if (!MessageService.isCheckBit(req)){
            ReferenceCountUtil.release(buf);
            throw new ServiceExcep(ServiceExceptionEume.MESSAGEISNOTCHECK,Util.BCD2String(req));
        }
//        LOGGER.info("客户端"+ channelHandlerContext.channel().id().toString() + ",接收到了："+info);
        String commandId = MessageService.getCommandControl(req);
        messageFactoryService.sendMsg(channelHandlerContext,req);
        //        //ByteBuf pingMessage = Unpooled.buffer();
        //pingMessage.writeBytes(req);
        //channelHandlerContext.writeAndFlush(pingMessage);
        ReferenceCountUtil.release(buf);
        //服务端使用这个就能向 每个连接上来的客户端群发消息
//        //NettyConfig.group.writeAndFlush(info);
////    	Iterator<Channel> iterator = NettyConfig.group.iterator();
////    	while(iterator.hasNext()){
////    		//打印出所有客户端的远程地址
////    		System.out.println((iterator.next()).remoteAddress());
////    	}
    }

}
